#pragma once

#include <functional>
#include <optional>

template <typename T>
using ref = std::reference_wrapper<T>;

template <class T>
using option = std::optional<T>;

/// @brief True if any element in the parameter pack is true
template <typename... Args>
constexpr bool any() {
  return (... || Args::value);
};

/// @brief True if all parameter pack is true
template <typename... Args>
constexpr bool all(Args... args) {
  return (... && args);
}

template <typename R, typename... Args>
constexpr std::function<R(Args...)> make_function(R (&&func)(Args...)) {
  return std::function<R(Args...)>(func);
};

template <typename... T>
struct Or : std::integral_constant<bool, any<T...>()> {};

namespace qbe::ecs {
class App;
class Plugin;
class Scheduler;
class World;
class Time;
class EventBase;

template <typename T>
class Event;

template <typename T>
class EventWriter;

template <typename T>
class EventReader;

template <typename Content>
class Resource;

template <typename T>
inline std::string typeNameToString() {
  const char* typeNameCStr = typeid(T).name();
  return std::string(typeNameCStr);
}

}  // namespace qbe::ecs
